package com.matrixlearning.service;

import Jama.EigenvalueDecomposition;
import Jama.Matrix;
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.EigenDecomposition;
import org.apache.commons.math3.linear.RealMatrix;
import org.springframework.stereotype.Component;

@Component
public class ComputeService {
    /**
     * Auther sun
     * DATE 2023/3/18 19:23
     * VERSION 1.0
     */

    public String addSub(String shape, String matrix1, String matrix2, String select) {
        StringBuilder builder = new StringBuilder();
        String[] s1 = matrix1.split(" ");
        String[] s2 = matrix2.split(" ");
        if(select.equals("add")) {
            for(int i = 0; i < s1.length; i++) {
                Integer temp = Integer.parseInt(s1[i]) + Integer.parseInt(s2[i]);
                builder.append(temp);
                builder.append(" ");
            }
        }else {
            for(int i = 0; i < s1.length; i++) {
                Integer temp = Integer.parseInt(s1[i]) - Integer.parseInt(s2[i]);
                builder.append(temp);
                builder.append(" ");
            }
        }
        return builder.toString();
    }

    /**
     * Jama库，求特征值和特征向量
     * @param shape
     * @param matrix1
     * @return
     */
    public String[] characterValue(String shape, String matrix1) {
        int n = Integer.parseInt(shape);
        String[] s = matrix1.split(" ");
        double[][] inputMatrix = new double[n][n];
        for(int i=0;i<n;i++) {
            for(int j=0;j<n;j++) {
                inputMatrix[i][j] = Integer.parseInt(s[j+i*n]);
            }
        }
        StringBuilder vector = new StringBuilder();
        StringBuilder value = new StringBuilder();
        Matrix matrix = new Matrix(inputMatrix);
        EigenvalueDecomposition eigen = new EigenvalueDecomposition(matrix); // 计算特征值和特征向量
        Matrix eigenvectors = eigen.getV(); // 特征向量矩阵
        double[][] array = eigenvectors.getArray();
        for(int i=0;i<array.length;i++) {
            for(int j=0;j<array[0].length;j++) {
                String str = String.format("%.2f",array[i][j]);
                vector.append(str);
                vector.append(" ");
            }
        }
        double[] eigenvalues = eigen.getRealEigenvalues(); // 获取特征值
        for (double eigenvalue : eigenvalues) {
            // 打印特征值
            String str = String.format("%.2f",eigenvalue);
            value.append(str);
            value.append(" ");
        }

        return new String[]{vector.toString(), value.toString()};
    }

    //高斯-约旦消元法
    public int[][] ladderMatrix(String shape, String matrix1) {
        String[] s1 = matrix1.split(" ");
        String[] s = shape.split(" ");
        int rowCount = Integer.parseInt(s[0]);
        int columnCount = Integer.parseInt(s[1]);
        int[][] matrix = new int[rowCount][columnCount];
        for(int i=0;i<rowCount;i++) {
            for(int j = 0; j<columnCount; j++) {
                matrix[i][j] = Integer.parseInt(s1[j+i*columnCount]);
            }
        }
        int lead = 0;
        for (int r = 0; r < rowCount; r++) {
            if (lead >= columnCount) {
                break;
            }
            int i = r;
            while (matrix[i][lead] == 0) {
                i++;
                if (i == rowCount) {
                    i = r;
                    lead++;
                    if (lead == columnCount) {
                        return matrix;
                    }
                }
            }
            int[] temp = matrix[i];
            matrix[i] = matrix[r];
            matrix[r] = temp;

            double lv = matrix[r][lead];
            for (int j = 0; j < columnCount; j++) {
                matrix[r][j] /= lv;
            }

            for (int k = 0; k < rowCount; k++) {
                if (k != r) {
                    double multiplier = matrix[k][lead];
                    for (int j = 0; j < columnCount; j++) {
                        matrix[k][j] -= multiplier * matrix[r][j];
                    }
                }
            }
            lead++;
        }
        return matrix;
    }

    public String[] mult(String shape1, String shape2, String matrix1, String matrix2) {
        StringBuilder builder = new StringBuilder();
        String[] s = shape1.split(" ");
        String[] s2 = shape2.split(" ");
        int num1 = Integer.parseInt(s[0]);
        int num2 = Integer.parseInt(s[1]);
        int num3 = Integer.parseInt(s2[1]);
        String[] m1 = matrix1.split(" ");
        String[] m2 = matrix2.split(" ");
        int[][] a = new int[num1][num2];
        int[][] b = new int[num2][num3];
        int[][] c = new int[num1][num3];
        for(int i=0;i<num1;i++) {
            for(int j = 0; j<num2; j++) {
                a[i][j] = Integer.parseInt(m1[j+i*num2]);
            }
        }
        for(int i=0;i<num2;i++) {
            for(int j = 0; j<num3; j++) {
                b[i][j] = Integer.parseInt(m2[j+i*num3]);
            }
        }
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[i].length; j++) {
                for (int k = 0; k < b[j].length; k++) {
                    c[i][k] += a[i][j] * b[j][k];
                }
            }
        }
        for(int i=0;i<num1;i++) {
            for(int j=0;j<num3;j++) {
                builder.append(c[i][j]);
                builder.append(" ");
            }
        }
        String result = builder.toString();
        return new String[]{result,String.valueOf(num1),String.valueOf(num3)};
    }

    public String numMult(String shape, String matrix1, String number) {
        String[] matrix = matrix1.split(" ");
        StringBuilder builder = new StringBuilder();
        int num = Integer.parseInt(number);
        for(int i = 0; i < matrix.length; i++) {
            int temp = Integer.parseInt(matrix[i]);
            builder.append(temp * num);
            builder.append(" ");
        }
        return builder.toString();
    }

    /**
     * 相似对角化
     * @param shape
     * @param matrix1
     * @return
     */
    public String[] similiarDiag(String shape, String matrix1) {
        StringBuilder builder1 = new StringBuilder();
        StringBuilder builder2 = new StringBuilder();
        int n = Integer.parseInt(shape);
        String[] s = matrix1.split(" ");
        double[][] inputMatrix = new double[n][n];
        for(int i=0;i<n;i++) {
            for(int j=0;j<n;j++) {
                inputMatrix[i][j] = Integer.parseInt(s[j+i*n]);
            }
        }
        RealMatrix matrixA = new Array2DRowRealMatrix(inputMatrix);

        // 进行相似对角化
        EigenDecomposition eigenDecomposition = new EigenDecomposition(matrixA);
        RealMatrix diagonalMatrix = eigenDecomposition.getD(); // 对角矩阵
        RealMatrix similarityMatrix = eigenDecomposition.getV(); // 相似变换矩阵
        // 输出结果
        System.out.println("对角矩阵D：\n" + diagonalMatrix);
        double[][] data1 = diagonalMatrix.getData();

        System.out.println("相似变换矩阵P：\n" + similarityMatrix);
        double[][] data2 = similarityMatrix.getData();

        for(int i=0;i<data1.length;i++) {
            for(int j=0;j<data1[0].length;j++) {
                String str = String.format("%.2f",data1[i][j]);
                builder1.append(str);
                builder1.append(" ");
            }
        }
        for(int i=0;i<data2.length;i++) {
            for(int j=0;j<data2[0].length;j++) {
                String str = String.format("%.2f",data2[i][j]);
                builder2.append(str);
                builder2.append(" ");
            }
        }
        return new String[]{builder1.toString(), builder2.toString()};
    }



}
